; int comprimir_buffer(unsigned char *scr_buf, unsigned int scr_size, unsigned char **dst_buf, unsigned int *dst_size, codigo_t **tabla_codigos, unsigned int *long_codificacion);

%include "macros/personalizada.mac"

extern generar_tabla_apariciones
extern generar_tabla_codigos
extern calcular_longitud_codificacion
extern generar_codificacion
extern free
extern malloc

global comprimir_buffer

%define ptr_tabla_apariciones [ebp - 4]
%define ptr_src_buf [ebp + 8]
%define src_size [ebp + 12]
%define ptr_ptr_dst_buf [ebp + 16]
%define ptr_dst_size [ebp + 20]
%define ptr_ptr_tabla_codigos [ebp + 24]
%define ptr_long_codificacion [ebp + 28]

section .text

comprimir_buffer:
	push ebp
	mov ebp, esp
	sub esp, 4
	push esi
	push edi
	push ebx
	
	mov eax, src_size
	mov esi, ptr_src_buf
	
	; Creamos la tabla de apariciones.
	; unsigned int * generar_tabla_apariciones(unsigned char *buf, unsigned int size);
	push eax
	push esi
	call generar_tabla_apariciones
	add esp, 8
	cmp eax, 0
	je NEAR error
	mov ptr_tabla_apariciones, eax ; Guardo en ptr_tabla_apariciones(var local) el ptr a la tabla.
	
	; Creamos la tabla de codigos.
	; codigo_t * generar_tabla_codigos(unsigned int *tabla_apariciones);
	push eax
	call generar_tabla_codigos
	add esp, 4
	cmp eax, 0
	je NEAR error
	mov esi, ptr_ptr_tabla_codigos ; Guardo el  ptr de la tabla de codigos en la dir de entrada.
	mov [esi], eax
	
	; Calculamos la longitud del archivo comprimido.
	; int calcular_longitud_codificacion(unsigned int *tabla_apariciones, codigo_t *tabla_codigo);
	mov esi, ptr_tabla_apariciones
	push eax
	push esi
	call calcular_longitud_codificacion
	add esp, 8
	cmp eax, 0
	je error
	
	mov esi, ptr_long_codificacion
	mov [esi], eax ; Guardo la longitud de la codificacion.
	
	; Calculamos la memoria en bytes para el buffer destino.
	xor edx, edx ; Limpio edx
	mov ebx, 8
	div ebx	; Divido eax por 8. Asi obtengo la longitud en bytes.
	cmp edx, 0 ; Me fijo que tengo en el resto.
	je no_sumo ; Si tengo resto reservo un byte mas.
	add eax, 1
no_sumo:
	mov esi, ptr_dst_size
	mov [esi], eax
	mov ebx, eax
	
	; Reservamos memoria para el buffer destino.
	push eax
	call malloc
	add esp, 4
	cmp eax, 0
	je error
	
	mov esi, ptr_ptr_dst_buf
	mov [esi], eax ; Guardo el ptr al dst_buf en la dir de entrada.
	
	; Realizamos la codificacion del buffer de entrada y lo guardamos en el buffer destino.
	mov esi, ptr_src_buf
	mov edi, src_size
	mov ecx, ptr_ptr_tabla_codigos ; Guardo el  ptr de la tabla de codigos en la dir de entrada.
	mov ecx, [ecx]
	push ecx
	push ebx
	push eax
	push edi
	push esi
	call generar_codificacion
	add esp, 20
	cmp eax, 0
	jne error
	
	; Liberamos la memoria de la tabla de apariciones.
	mov eax, ptr_tabla_apariciones
	push eax
	call free
	add esp, 4
	
	xor eax, eax ; La funcion termino con exito y retorna 0.
	jmp fin
	
error:
	mov eax, error_code ; La funcion fallo y retorna un codigo de error.
	
fin:
	pop ebx
	pop edi
	pop esi
	add esp, 4
	pop ebp
	ret
